{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "102fb65c",
   "metadata": {},
   "outputs": [],
   "source": [
    "%use fuel(2.3.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5324ea09",
   "metadata": {},
   "outputs": [],
   "source": [
    "val envs = java.io.File(\"../../.env\")\n",
    "    .readLines()\n",
    "    .map {\n",
    "        it.split(\"=\")[0] to it.split(\"=\")[1].trim('\"')\n",
    "    }.toMap()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "40ba536f",
   "metadata": {},
   "outputs": [],
   "source": [
    "val session = envs.get(\"AOC_SESSION\")\n",
    "val year = 2021\n",
    "val day = 21"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e0ad68af",
   "metadata": {},
   "outputs": [],
   "source": [
    "fun getInput(year: Int, day: Int, session: String): String {\n",
    "    val (_, _, result) = \"https://adventofcode.com/$year/day/$day/input\"\n",
    "    .httpGet()\n",
    "    .header(\"cookie\" to \"session=$session\")\n",
    "    .responseString()\n",
    "        \n",
    "    return result.get().trim()\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "da6aac0f",
   "metadata": {},
   "outputs": [],
   "source": [
    "fun submitAnswer(year: Int, day: Int, session: String, level: Int, answer: String): String {\n",
    "    val (_, _, result) = Fuel\n",
    "    .post(\n",
    "        \"https://adventofcode.com/$year/day/$day/answer\", \n",
    "        parameters = listOf(\"level\" to level, \"answer\" to answer))\n",
    "    .header(\"cookie\" to \"session=$session\")\n",
    "    .responseString()\n",
    "        \n",
    "    return result.get()\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "41dc0779",
   "metadata": {},
   "outputs": [],
   "source": [
    "val sample = \"\"\"Player 1 starting position: 4\n",
    "Player 2 starting position: 8\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "0f76344c",
   "metadata": {},
   "outputs": [],
   "source": [
    "val input = getInput(year, day, session)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a2007b1c",
   "metadata": {},
   "outputs": [],
   "source": [
    "fun partOne(input: String): String {\n",
    "    class Die {\n",
    "        var rolls = 0\n",
    "        var v = 1\n",
    "        \n",
    "        fun roll(times: Int): Int {\n",
    "            var sum = 0\n",
    "            repeat(times) {\n",
    "                sum += v\n",
    "                v++\n",
    "                rolls++\n",
    "                if (v > 100) v = 1\n",
    "            }\n",
    "            return sum\n",
    "        }\n",
    "    }\n",
    "    \n",
    "    var (a, b) = input.split(\"\\n\").map {\n",
    "        it.split(\": \")[1].toInt()\n",
    "    }\n",
    "    var pa = 0\n",
    "    var pb = 0\n",
    "    val die = Die()\n",
    "    \n",
    "    while (pa < 1000 && pb < 1000) {\n",
    "        a = (a + die.roll(3) - 1) % 10 + 1\n",
    "        pa += a\n",
    "        if (pa >= 1000) break\n",
    "        \n",
    "        b = (b + die.roll(3) - 1) % 10 + 1\n",
    "        pb += b\n",
    "    }\n",
    "    \n",
    "    return (pa.coerceAtMost(pb) * die.rolls).toString()\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0c4aaa1f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "739785"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "partOne(sample)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "bbdc829d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1006866"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "val partOneAns = partOne(input)\n",
    "partOneAns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "92bdbfa2",
   "metadata": {},
   "outputs": [],
   "source": [
    "submitAnswer(year, day, session, 1, partOneAns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4ece53d8",
   "metadata": {},
   "outputs": [],
   "source": [
    "fun partTwo(input: String): String {\n",
    "    val (a, b) = input.split(\"\\n\").map {\n",
    "        it.split(\": \")[1].toInt()\n",
    "    }\n",
    "    \n",
    "    val dp = Array(22) { Array(22) { Array(11) { Array(11) { LongArray(2) } } } }\n",
    "    dp[0][0][a][b][0] = 1\n",
    "    val coeff = listOf<Long>(0, 0, 0, 1, 3, 6, 7, 6, 3, 1)\n",
    "    \n",
    "    for (pa in 0 until 21) for (pb in 0 until 21) for (q in 0..1) for (a in 1..10) for (b in 1..10) {\n",
    "        if (dp[pa][pb][a][b][q] == 0L) continue\n",
    "        \n",
    "        if (q == 0) {\n",
    "            for (die in 3..9) {\n",
    "                val a1 = (a + die - 1) % 10 + 1\n",
    "                val pa1 = (pa + a1).coerceAtMost(21)\n",
    "                dp[pa1][pb][a1][b][1 - q] += dp[pa][pb][a][b][q] * coeff[die]\n",
    "            }\n",
    "        } else {\n",
    "            for (die in 3..9) {\n",
    "                val b1 = (b + die - 1) % 10 + 1\n",
    "                val pb1 = (pb + b1).coerceAtMost(21)\n",
    "                dp[pa][pb1][a][b1][1 - q] += dp[pa][pb][a][b][q] * coeff[die]\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "    \n",
    "    var aWin = 0L\n",
    "    var bWin = 0L\n",
    "    for (pb in 0 until 21) for (q in 0..1) for (a in 1..10) for (b in 1..10) aWin += dp[21][pb][a][b][q]\n",
    "    for (pa in 0 until 21) for (q in 0..1) for (a in 1..10) for (b in 1..10) bWin += dp[pa][21][a][b][q]\n",
    "    \n",
    "    return (aWin.coerceAtLeast(bWin)).toString()\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "78bdab44",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "444356092776315"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "partTwo(sample)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "1408f167",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "273042027784929"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "val partTwoAns = partTwo(input)\n",
    "partTwoAns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "103227b5",
   "metadata": {},
   "outputs": [],
   "source": [
    "submitAnswer(year, day, session, 2, partTwoAns)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Kotlin",
   "language": "kotlin",
   "name": "kotlin"
  },
  "language_info": {
   "codemirror_mode": "text/x-kotlin",
   "file_extension": ".kt",
   "mimetype": "text/x-kotlin",
   "name": "kotlin",
   "nbconvert_exporter": "",
   "pygments_lexer": "kotlin",
   "version": "1.6.20-dev-6372"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
